﻿using Microsoft.EntityFrameworkCore;
using PioneerBoilerplate.Model.Admin;
using PioneerBoilerplate.Repository;
using PioneerBoilerplate.Repository.Repositories;
using PioneerBoilerplate.Repository.UnitOfWorks;
using PioneerBoilerplate.Service.Admin.DictionaryType.Input;
using PioneerBoilerplate.Service.Admin.DictionaryType.Output;
using PioneerBoilerplate.Service.Base;
using PioneerBoilerplate.Util;
using PioneerBoilerplate.Util.Input;
using PioneerBoilerplate.Util.Output;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace PioneerBoilerplate.Service.Admin.DictionaryType
{
    public class DictionaryTypeService : BaseService, IDictionaryTypeService
    {
        private readonly IDictionaryTypeRepository _dictionaryTypeRepository;
        private readonly IDictionaryRepository _dictionaryRepository;
        private readonly IUnitOfWorkManager _unitOfWorkManager;
        public DictionaryTypeService(
            IDictionaryTypeRepository dictionaryTypeRepository, 
            IDictionaryRepository dictionaryRepository,
            IUnitOfWorkManager unitOfWorkManager)
        {
            _dictionaryTypeRepository = dictionaryTypeRepository;
            _dictionaryRepository = dictionaryRepository;
            _unitOfWorkManager = unitOfWorkManager;
        }

        public async Task<IResponseOutput> GetAsync(long id)
        {
            var result = Mapper.Map<DictionaryTypeGetOutput>(await _dictionaryTypeRepository.FirstOrDefaultAsync(a => a.Id == id));
            return ResponseOutput.Ok(result);
        }

        public async Task<IResponseOutput> PageAsync(PageInput<DictionaryTypeEntity> input)
        {
            var key = input.Filter?.Name;

            PaginationSpecification<DictionaryTypeEntity> specification = new();
            specification.WhereIf(key.NotNull(), e => e.Name.Contains(key));
            specification.OrderBy = q => q.OrderByDescending(e => e.Id);
            specification.PageIndex = input.CurrentPage;
            specification.PageSize = input.PageSize;

            var list = await _dictionaryTypeRepository.GetListAsync(specification);
            var data = new PageOutput<DictionaryTypeEntity>()
            {
                List = Mapper.Map<List<DictionaryTypeEntity>>(list.Items),
                Total = list.TotalItems
            };

            return ResponseOutput.Ok(data);
        }

        public async Task<IResponseOutput> AddAsync(DictionaryTypeAddInput input)
        {
            var DictionaryType = Mapper.Map<DictionaryTypeEntity>(input);
            var id = (await _dictionaryTypeRepository.InsertAsync(DictionaryType)).Id;
            return ResponseOutput.Result(id > 0);
        }

        public async Task<IResponseOutput> UpdateAsync(DictionaryTypeUpdateInput input)
        {
            if (!(input?.Id > 0))
            {
                return ResponseOutput.NotOk();
            }

            var entity = await _dictionaryTypeRepository.FirstOrDefaultAsync(a => a.Id == input.Id);
            if (!(entity?.Id > 0))
            {
                return ResponseOutput.NotOk("数据字典不存在！");
            }

            Mapper.Map(input, entity);
            await _dictionaryTypeRepository.UpdateAsync(entity);
            return ResponseOutput.Ok();
        }

        public async Task<IResponseOutput> DeleteAsync(long id)
        {
            using (var uowHandle = _unitOfWorkManager.Begin<ApplicationDbContext>())
            {
                //删除字典数据
                var dictionaries = await _dictionaryRepository.GetAll().Where(a => a.DictionaryTypeId == id).ToListAsync();
                dictionaries?.ForEach(async dictionary => 
                { 
                    await _dictionaryRepository.DeleteAsync(dictionary); 
                });

                //删除字典类型
                var dictionaryType = await _dictionaryTypeRepository.GetAll().Where(a => a.Id == id).FirstOrDefaultAsync();
                await _dictionaryTypeRepository.DeleteAsync(dictionaryType);

                uowHandle.SaveChange();
            }
            return ResponseOutput.Ok();
        }

        public async Task<IResponseOutput> SoftDeleteAsync(long id)
        {
            using (var uowHandle = _unitOfWorkManager.Begin<ApplicationDbContext>())
            {
                //删除字典数据
                var dictionaries = await _dictionaryRepository.GetAll().Where(a => a.DictionaryTypeId == id).ToListAsync();
                dictionaries?.ForEach(async dictionary => 
                {
                    dictionary.IsDeleted = true;
                    await _dictionaryRepository.UpdateAsync(dictionary); 
                });

                //删除字典类型
                var dictionaryType = await _dictionaryTypeRepository.GetAll().Where(a => a.Id == id).FirstOrDefaultAsync();
                dictionaryType.IsDeleted = true;
                await _dictionaryTypeRepository.UpdateAsync(dictionaryType);

                uowHandle.SaveChange();
            }
            return ResponseOutput.Ok();
        }

        public async Task<IResponseOutput> BatchSoftDeleteAsync(long[] ids)
        {
            using (var uowHandle = _unitOfWorkManager.Begin<ApplicationDbContext>())
            {
                //删除字典数据
                var dictionaries = await _dictionaryRepository.GetAll().Where(a => ids.Contains(a.DictionaryTypeId)).ToListAsync();
                dictionaries?.ForEach(async dictionary =>
                {
                    dictionary.IsDeleted = true;
                    await _dictionaryRepository.UpdateAsync(dictionary);
                });

                //删除字典类型
                var dictionaryTypes = await _dictionaryTypeRepository.GetAll().Where(a=>ids.Contains(a.Id)).ToListAsync();
                dictionaryTypes?.ForEach(async dictionaryType =>
                {
                    dictionaryType.IsDeleted = true;
                    await _dictionaryTypeRepository.UpdateAsync(dictionaryType);
                });
                
                uowHandle.SaveChange();
            }
            return ResponseOutput.Ok();
        }
    }
}